home *** CD-ROM | disk | FTP | other *** search
/ HamCall (October 1991) / HamCall (Whitehall Publishing)(1991).bin / prgming / ada / pnote1.doc < prev    next >
Text File  |  1987-10-14  |  5KB  |  109 lines

  1.  5-Apr-86 14:51:29-MST,4792;000000000001
  2. Return-Path: <@USC-ISIF.ARPA:info-ada-request@usc-isif.arpa>
  3. Received: from USC-ISIF.ARPA by SIMTEL20.ARPA with TCP; Sat 5 Apr 86 14:51:20-MST
  4. Received: FROM berkeley BY USC-ISIF.ARPA WITH TCP ; 5 Apr 86 13:10:48 PST
  5. Received: by ucbvax.berkeley.edu (5.48/1.11)
  6.     id AA01699; Sat, 5 Apr 86 12:34:03 PST
  7. Date: 4 Apr 86 13:36:35 GMT
  8. From: sftig!sfsup!sfmag!sftor!cw@ucbvax.berkeley.edu  (C.S.Wetherell)
  9. Organization: AT&T Bell Laboratories, Summit N.J.
  10. Subject: Two characteristic programming errors in Ada
  11. Message-Id: <951@sftor.UUCP>
  12. Sender: postmaster@usc-isif.arpa (fix your mailer)
  13. Real-Annoyed-Sender: usenet@ucbvax.berkeley.edu
  14. Errors-To: <info-ada-request@usc-isif.arpa>
  15. To: info-ada@usc-isif.arpa
  16.  
  17. While porting some programs from the Simtel20 archives to our new
  18. compiler, I had some difficulty with one of them.  Upon investigation,
  19. I discovered two subtle but characteristic misuses of Ada.  I am sure they
  20. are quite common, so I will protect the author.
  21.  
  22. Consider the following procedure declaration (ignore its innards for 
  23. the moment)
  24.  
  25.    procedure Does_A_Check(Formal : in out NATURAL);
  26.  
  27. and the skeletal calling routine
  28.  
  29.    with Does_A_Check;
  30.    procedure Im_A_Caller is
  31.       Actual : NATURAL;
  32.    begin
  33.       Does_A_Check(Actual);
  34.    end;
  35.  
  36. When this pair was linked and executed, a constraint exception was raised at
  37. the point of call.  [This happened to be particularly mystifying in the
  38. ported program, because the program was carefully taking care of all
  39. exceptions and I couldn't tell at first exactly what was causing the
  40. program to fail. Some embedding of trace statements uncovered the 
  41. difficulty after a bit.]  Of course, the reason the constraint error
  42. was raised was that variable Actual in Im_A_Caller was not
  43. initialized; there is no requirement that the initial value of
  44. a variable be within its declared bounds (with exception of access
  45. types, of course).  Since formal in-out parameters are checked
  46. for constraints at procedure entry, a constraint error was raised.
  47. I can only assume that the particular program had always been compiled
  48. and executed on a system where the initial values were within bounds;
  49. this is, of course, an example of a bug common to other languages as
  50. well.
  51.  
  52. However, there is a second bug in the program.  Let us now
  53. consider the body of Does_A_Check:
  54.  
  55.    procedure Does_A_Check(Formal : in out NATURAL) is
  56.    begin
  57.       Formal := 0;
  58.       ...
  59.       Something := ... Formal ...;
  60.       ...
  61.    end;
  62.  
  63. Notice that the first thing Does_A_Check executes is an initializing
  64. assignment to Formal; the routine really doesn't care about the 
  65. in-bound value of the actual argument at all.  In fact, the only
  66. reason that Formal is declared "in out" is so that it can be used
  67. on the right-hand side of some statements.  Now, the Ada rule is that
  68. an "out" parameter cannot be so used; the parameter may have an
  69. undefined value at some places of such usage and the rules about
  70. no right-hand usage keep the compiler from having to do a flow
  71. analysis to determine if a particular usage is after a definition.
  72. Here, the programmer, to save declaring a local variable, just made
  73. Formal "in out"; then it can be used on the right.  But the cost is
  74. unexpected constraint errors or extra work for the caller; 
  75. after all, the caller doesn't know (in theory) why the formal parameter
  76. is "in out" and may have to go to considerable trouble to guarantee that
  77. the actual argument has an acceptable value; this is disturbing when 
  78. the formal doesn't really need the initial value.
  79.  
  80. The moral seems to be to use "in out" parameters only when the
  81. called routine actually needs the initial value; otherwise, use
  82. a paradigm like
  83.  
  84.     procedure Does_A_Check(Formal : out NATURAL) is
  85.            Local : NATURAL;
  86.         begin
  87.            Local := 0; -- yes, this could be done in the declaration.
  88.            ...
  89.            Something := ... Local ...
  90.            ...
  91.            Formal := Local;
  92.            return;
  93.         end Does_A_Check;
  94.  
  95. Finally, I might note that this problem was uncovered partly because our
  96. compiler temporarily is storing characters in 16-bits while a little
  97. part of our code generator is undergoing additional education about
  98. the differences between signed and unsigned bytes.  One version of the
  99. problem was using characters instead of NATURAL's. If the Actual
  100. from above had been an 8-bit character, it might have been automatically
  101. truncated to within the constraints; as a 16-bit character, it was not.
  102. There is no guarantee in Ada about the sizes of types beyond the rules
  103. governing type declarations; this particular stretch of code was
  104. mildly unrobust in the face of changing sizes
  105.  
  106. Charles Wetherell
  107. AT&T Information Systems
  108. Summit NJ
  109.